home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
276-300
/
disk_290
/
ipc
/
sources
/
formatclient.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
12KB
|
329 lines
/************************************************************
* *
* Minimal Print server Client Demo for IPC *
* *
* -- Shared Library Version -- *
* *
* Pete Goodeve 89:11:27 *
* *
* [This module has only been compiled under Lattice; *
* it will need some modification for Manx/Aztec; *
* ... I'd be very grateful if someone would do the *
* conversion...] *
* *
* *
* This is a simple test module for the "Print Format" *
* server. When you type the return key, it generates *
* a message with a set of items in various formats, *
* and sends it to the print server. (For test purposes *
* the items are fixed.) If you simply type a return, *
* the formatted string generated from the message is *
* displayed in the print server's own window; if you *
* type an 'F' before the return, a file handle to this *
* Client program's console window is passed in the *
* message and the string will be output to this instead; *
* if you type an 'M' before the return, the string will *
* be passed back in the reply message and again shown *
* in the Client's console window. *
* *
* Typing 'Q' will send a 'QUIT' message to the server *
* instead of a print request. To exit the client *
* program type an 'end-of-file' (cntrl-'\'); the *
* print server is currently programmed to exit also *
* when there are no running clients left. *
* *
* It is a simple "synchronous" client: when it sends a *
* message it waits for the reply before continuing *
* (unlike others that may continue with other activities *
* while the server is processing a message). The main *
* loop is simple: *
* *
* Wait for keyboard command *
* Send message *
* Wait for reply *
* Display string from reply if supplied *
* Loop to wait for keyboard again. *
* *
* *
************************************************************/
#ifdef LATTICE
#if LATTICE_40 | LATTICE_50
#include "IPC_proto.h"
/* ...else (not recent Lattice) will need library linkage stubs (IPC.o) */
#endif
#endif
#include "IPC.h"
#include "exec/memory.h"
#define LINESZ 120
#define SHOWREAL 1
/*
* Define the ID codes recognized by the print format server
*
* (MAKE_ID is defined in IPC.h)
*/
/* Message IDs: */
#define CNVA MAKE_ID('C','N','V','A')
/* CoNVert to Ascii */
#define QUIT MAKE_ID('Q','U','I','T')
/* Item IDs: */
#define RETS MAKE_ID('R','E','T','S')
/* RETurn String */
#define FILH MAKE_ID('F','I','L','H')
/* FILe Handle */
#define PATS MAKE_ID('P','A','T','S')
/* PATtern String */
#define PAT1 MAKE_ID('P','A','T','1')
/* PATtern -- 1 item */
#define LINE MAKE_ID('L','I','N','E')
/* indicates a complete line of text -- omitting newline */
#define TEXT MAKE_ID('T','E','X','T')
/* Text block -- may include newlines */
#define STRG MAKE_ID('S','T','R','G')
/* general non-specific ASCII STRinG */
/* The above three categories are treated identically by Pserver
-- they may have distinct meanings to other servers */
#define CHAR MAKE_ID('C','H','A','R')
/* A single character in L.S byte of ii_Ptr */
#define INTG MAKE_ID('I','N','T','G')
/* A 32-bit INTeGer in ii_Ptr */
#define REAL MAKE_ID('R','E','A','L')
/* A 32-bit floating point value in ii_Ptr (care in conversion!) */
/*******************
rather than the above if you prefer, with Lattice 4.0 you can simply
use 4-character constants as in the following (compile with the -cm option):
#define CNVA 'CNVA'
#define QUIT 'QUIT'
#define RETS 'RETS'
#define FILH 'FILH'
#define PATS 'PATS'
#define PAT1 'PAT1'
#define LINE 'LINE'
#define TEXT 'TEXT'
#define STRG 'STRG'
#define CHAR 'CHAR'
#define INTG 'INTG'
#define REAL 'REAL'
*********************/
APTR IPCBase = NULL;
struct IPCPort *port=NULL; /* will point to server port */
struct MsgPort *rport=NULL; /* where we get our replies */
struct IPCMessage *imsg=NULL; /* this one message is used repeatedly */
struct MsgPort * CreatePort(char *, int);
ULONG Output();
void Cleanup();
void outputstr(char *);
/***************************
*
* Main program entry point:
*
* -- Note that to save overhead we use '_main'; you should also compile
* (under Lattice) using the -v switch, to suppress stack checking and
* the associated baggage.
*
* We avoid using any C level I/O also -- just AmigaDOS calls, so we
* dont need <stdio.h>.
*/
void _main()
{
struct IPCItem *item, *item0; /* pointers to access message items */
int count=0; /* dummy value used to stuff into message */
float realcount=0.0; /* -- ditto */
char tbuf[22]; /* keyboard input dumped in here */
/* Before anything else, we need the IPC Library: */
IPCBase = (APTR)OpenLibrary("ppipc.library",0);
if (!IPCBase) {
outputstr(
"Couldn't find ppipc.library!\nHave you installed it in LIBS: ?\n");
_exit(20);
}
/* First we set up our ports: */
port = LoadIPCPort("Print_Format"); /* try the Port Broker first */
if (!port) /* gimmicked so it can be used with or without Broker */
port = GetIPCPort("Print_Format");
if (!port) {Cleanup(); _exit(21);}
rport = CreatePort(NULL,0);
if (!rport) {Cleanup(); _exit(21);}
/* ... then make a message block */
imsg = CreateIPCMsg(20,0,rport); /* large enough for playing with... */
if (!imsg) {Cleanup(); _exit(22);}
item0 = &imsg->ipc_Items[0]; /* a convenient permanent reference */
/* The main program loop:
* -- continues until told to quit by end-of-file (ctrl-\)
*/
while (1) {
item = item0; /* reset item pointer */
imsg->ipc_Id = CNVA; /* only message ID needed (except QUIT) */
/*
* Initially we assume that the first item will be a slot
* in which the server will return the formatted string.
* This will be overwritten if another option is chosen
*/
item->ii_Id = RETS;
item->ii_Ptr = NULL; /* The server will provide the data block */
item->ii_Size = 0;
item->ii_Flags = imsg->ipc_Flags = 0;
/* get keyboard input (terminated by return): */
/* E-O-F returns a length of zero, causing break from loop */
if (Read(Input(), tbuf, 21) <= 0) break;
/*
* decode first character of input to decide action
* (sorry about the crudity... but it suffices)
*/
switch(*tbuf) {
case 'Q': /* Send a QUIT message */
case 'q':
case '.': imsg->ipc_Id = QUIT; /* all items are ignored */
break;
case 'm': /* Request string in reply Message */
case 'M':
case '?': item++; /* leave default RETS in place */
item->ii_Id = STRG; /* Add in a string item to
distinguish displayed line */
item->ii_Ptr = (void *)("Returned: ");
item++;
break;
case 'F': /* Pass File handle to this console */
case 'f':
case '^': item->ii_Id = FILH; /* overwrites RETS */
item++->ii_Ptr = (void *)Output(); /* the file handle */
break;
default: /* anything else just overwrites RETS with output
items, so string appears on Pserver window */
break;
}
/*
* The rest of the setup code simply stuffs a few values of
* different types into successive items -- rearrange to your
* own satisfaction...
* NOTE that we haven't bothered to put the strings into public
* memory, contrary to the suggestions of the IPC standard
* [For shame, Peter!] but this is really only a restriction
* that needs to be observed for general messages that may have
* a destination outside the ken of the sender (or for a future
* machine that has process-private memory). This isn't relevant
* to such a simple test program, so we've simplified things.
* At the same time, the ii_Size field for the string items is
* set to ZERO, indicating that the "data block" is Read-Only
* as far as the server is concerned.
*/
item->ii_Id = STRG; /* A short string to start out with */
item->ii_Ptr = (void *)("Test line...");
item++;
item->ii_Id = PAT1; /* then a format specifier for a value */
item->ii_Ptr = (void *)(" #%3d");
item++;
item->ii_Id = INTG; /* the integer value to be formatted */
item->ii_Ptr = (void *)(count++); /* (just a sequential count...) */
item++;
item->ii_Id = STRG; /* another string... */
item->ii_Ptr = (void *)("... value=");
item++;
item->ii_Id = REAL; /* A float value in default format */
/* note the messy conversion to get it into the ii_Ptr field */
*(float *) &item->ii_Ptr = (realcount += 1.234);
item++;
item->ii_Id = CHAR; /* and a newline character to end the section */
item->ii_Ptr = (void *)('\n');
item++;
item->ii_Id = PATS; /* Multi item format specifier */
item->ii_Ptr = (void *)("formatted line #%2d %s\n");
item++;
item->ii_Id = INTG;
item->ii_Ptr = (void *)(count++);
item++;
item->ii_Id = STRG;
item->ii_Ptr = (void *)((count & 3) ? "..." : "tick...");
/* no more items allowed after PATS is satisfied */
/* set actual ItemCount into message: */
imsg->ipc_ItemCount = item - item0 + 1;
/* Send the message (if possible) */
if (!PutIPCMsg(port, imsg)) {
outputstr("No server!\n");
continue; /* don't wait for a reply that won't come! */
}
/* Wait at the reply port: */
WaitPort(rport);
GetMsg(rport); /* we assume we know what's there! */
if (imsg->ipc_Flags & IPC_NOTKNOWN)
outputstr("Server barfed\n");
/*
* If we asked for a return string, display it in our
* window, then dispose of the block of memory passed to us
* by the server:
*/
if (item0->ii_Id == RETS) {
Write(Output(), item0->ii_Ptr, strlen(item0->ii_Ptr));
/* note that we DON'T use the ii_Size value above!
There is no guarantee that it is exactly the size of
the string. */
FreeMem(item0->ii_Ptr, item0->ii_Size);
}
}
/*** end of main loop ***/
Cleanup();
}
void Cleanup()
{
if (port) DropIPCPort(port);
if (rport) DeletePort(rport);
if (imsg) DeleteIPCMsg(imsg);
CloseLibrary(IPCBase);
}
void outputstr(str) char *str;
{
Write(Output(), str, strlen(str));
}